package com.tca.common.learning.apollo.listener;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import com.tca.common.core.utils.ValidateUtils;
import com.tca.common.learning.apollo.config.TcaConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author an.zhou
 * @date 2023/1/4 15:25
 */
@Component
@Slf4j
public class ApolloTcaConfigListener {

    @ApolloConfig
    private Config config;

    @Autowired
    private TcaConfig tcaConfig;

    @ApolloConfigChangeListener
    public void configChangeListener(ConfigChangeEvent configChangeEvent) {
        refreshTcaConfig(configChangeEvent);
    }

    private void refreshTcaConfig(ConfigChangeEvent configChangeEvent) {
        Set<String> changedKeys = configChangeEvent.changedKeys();
        List<Method> methodList = Arrays.stream(tcaConfig.getClass().getMethods()).filter(m -> m.getName().startsWith("set"))
                .collect(Collectors.toList());

        for (String changedKey : changedKeys) {
            if (changedKey.startsWith("tca")) {
                ConfigChange configChange = configChangeEvent.getChange(changedKey);
                log.info("key : {}, has changed, oldValue = {}, newValue = {}", changedKey, configChange.getOldValue()
                        , configChange.getNewValue());
                String key = changedKey.substring(4);
                try {
                    List<Method> matchedMethodList = methodList.stream().filter(m -> m.getName().equalsIgnoreCase("set" + key))
                            .collect(Collectors.toList());
                    if (ValidateUtils.isEmpty(matchedMethodList)) {
                        throw new RuntimeException("no such method, methodName = " + "get" + key);
                    }
                    Method method = matchedMethodList.get(0);
                    Class<?> parameterType = method.getParameterTypes()[0];
                    if (parameterType == Integer.class) {
                        method.invoke(tcaConfig, Integer.parseInt(configChange.getNewValue()));
                    } else if (parameterType == Long.class) {
                        method.invoke(tcaConfig, Long.parseLong(configChange.getNewValue()));
                    } else if (parameterType == Double.class) {
                        method.invoke(tcaConfig, Double.parseDouble(configChange.getNewValue()));
                    } else {
                        method.invoke(tcaConfig, configChange.getNewValue());
                    }
                } catch (Exception e) {
                    log.error("转换出错", e);
                }
            }
        }


    }

}
